package game.targets.round;

import game.targets.entity.Entity;
import game.targets.entity.target.BadTarget;
import game.targets.entity.target.BonusTarget;
import game.targets.entity.target.NormalTarget;
import game.targets.entity.target.Target;
import game.targets.entity.target.TempTarget;
import game.targets.entity.target.TimeTarget;
import game.targets.observer.Subject;
import game.targets.room.Room;

import java.util.ArrayList;

import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector3;

public class Round {
	public static int MAX_TARGETS_PER_ROW = 5;
	public static float BONUS_CHANCE = 0.05f;
	public static float TARGET_DISTANCE = Room.DISTANCE_TO_TARGET_WALL + 3;
	public static float TEMP_TARGET_CHANCE = 0.05f;

	private ArrayList<Target> targets;
	private ArrayList<Integer> spaces;
	private ArrayList<TempTarget> tempTargets;
	private ArrayList<TempTarget> removed;
	private ArrayList<Entity> entities;
	private int number;
	private Subject subject;
	private float tempTimer;

	public Round(int number, ArrayList<Entity> entities, Subject subject) {
		this.number = number;
		this.subject = subject;
		targets = new ArrayList<Target>();
		spaces = new ArrayList<Integer>();
		tempTargets = new ArrayList<TempTarget>();
		removed = new ArrayList<TempTarget>();
		this.entities = entities;
		tempTimer = 0;
	}

	public void createRound() {
		targets.clear();
		if (number < 5) {
			createPattern(1);
		} else if (number < 10) {
			createPattern(5);
		} else if (number < 15) {
			createPattern(10);
		} else {
			createPattern(15);
		}
	}

	private void createPattern(int numOfTargets) {
		// create an array which holds the possible positions of targets
		spaces.clear();
		for (int i = 0; i < MAX_TARGETS_PER_ROW * MAX_TARGETS_PER_ROW; i++) {
			spaces.add(i);
		}
		// randomly assign targets positions
		for (int i = 0; i < numOfTargets; i++) {
			int position = MathUtils.random(0, spaces.size() - 1);
			position = spaces.remove(position);
			int positionY = position / MAX_TARGETS_PER_ROW;
			int positionX = position % MAX_TARGETS_PER_ROW;
			Target target = null;
			float chanceForBonus = MathUtils.random();
			// create a bonus target instead of a normal target
			if (chanceForBonus <= BONUS_CHANCE) {
				target = new BonusTarget(new Vector3(TARGET_DISTANCE, positionY * (Room.MAX_TARGET_WALL_HEIGHT / (MAX_TARGETS_PER_ROW - 1))
						+ Room.TARGET_WALL_POSITION_Y, positionX * (Room.MAX_TARGET_WALL_WIDTH / (MAX_TARGETS_PER_ROW - 1))
						+ Room.TARGET_WALL_POSITION_X), subject);
			} else {
				target = new NormalTarget(new Vector3(TARGET_DISTANCE, positionY * (Room.MAX_TARGET_WALL_HEIGHT / (MAX_TARGETS_PER_ROW - 1))
						+ Room.TARGET_WALL_POSITION_Y, positionX * (Room.MAX_TARGET_WALL_WIDTH / (MAX_TARGETS_PER_ROW - 1))
						+ Room.TARGET_WALL_POSITION_X), subject);
			}

			targets.add(target);
		}
	}

	public void createMovingPattern(int numOfTargets, int numMovingTargets) {

	}

	public void update(float delta) {
		tempTimer += delta;
		// update temporary targets
		for (TempTarget t : tempTargets) {
			t.update(delta);
			if (t.isDone()) {
				removed.add(t);
				targets.remove(t.getTarget());
				entities.remove(t.getTarget());
				t.getTarget().delete();
			}
		}
		tempTargets.removeAll(removed);
		removed.clear();

		// every second has a chance to spawn a temp target
		if (tempTimer >= 1 && tempTargets.size() < 2) {
			float r = MathUtils.random();
			if (r < TEMP_TARGET_CHANCE) {
				r = MathUtils.random();
				if (r <= 0.5f) {
					addTimeTarget();
				} else {
					addBadTarget();
				}
			}
			tempTimer = 0;
		}
		if (targets.isEmpty() || targets.size() == tempTargets.size()) {
			prepNextRound();
		}
	}
	
	public void prepNextRound(){
		for (TempTarget t : tempTargets) {
			targets.remove(t.getTarget());
			entities.remove(t.getTarget());
			t.getTarget().delete();
		}
		number++;
		tempTargets.clear();
		createRound();
		entities.addAll(targets);
	}

	public void addTimeTarget() {
		int position = MathUtils.random(0, spaces.size() - 1);
		position = spaces.remove(position);
		int positionY = position / MAX_TARGETS_PER_ROW;
		int positionX = position % MAX_TARGETS_PER_ROW;
		Target target = new TimeTarget(new Vector3(TARGET_DISTANCE, positionY * (Room.MAX_TARGET_WALL_HEIGHT / (MAX_TARGETS_PER_ROW - 1))
				+ Room.TARGET_WALL_POSITION_Y, positionX * (Room.MAX_TARGET_WALL_WIDTH / (MAX_TARGETS_PER_ROW - 1)) + Room.TARGET_WALL_POSITION_X),
				subject);
		targets.add(target);
		entities.add(target);
		TempTarget tt = new TempTarget(target);
		tempTargets.add(tt);
	}

	public void addBadTarget() {
		int position = MathUtils.random(0, spaces.size() - 1);
		position = spaces.remove(position);
		int positionY = position / MAX_TARGETS_PER_ROW;
		int positionX = position % MAX_TARGETS_PER_ROW;
		Target target = new BadTarget(new Vector3(TARGET_DISTANCE, positionY * (Room.MAX_TARGET_WALL_HEIGHT / (MAX_TARGETS_PER_ROW - 1))
				+ Room.TARGET_WALL_POSITION_Y, positionX * (Room.MAX_TARGET_WALL_WIDTH / (MAX_TARGETS_PER_ROW - 1)) + Room.TARGET_WALL_POSITION_X),
				subject);
		targets.add(target);
		entities.add(target);
		TempTarget tt = new TempTarget(target);
		tempTargets.add(tt);
	}
	
	public void tempTargetHit(Target target){
		TempTarget remove=null;
		for(TempTarget t:tempTargets){
			if(t.getTarget().equals(target)){
				remove=t;
				break;
			}
		}
		tempTargets.remove(remove);
	}

	public ArrayList<Target> getTargets() {
		return targets;
	}

	public void setTargets(ArrayList<Target> targets) {
		this.targets = targets;
	}

	public int getNumber() {
		return number;
	}

	public void setNumber(int number) {
		this.number = number;
	}

}
